/***********************************************************************
filename: 	hgeRect.cpp
created:	8/3/2004
author:		Paul D Turner

purpose:	Implements 'hgeRect' class
*************************************************************************/
#include "hgeRect.h"

/*************************************************************************
Constructor
*************************************************************************/
hgeRect::hgeRect(float left, float top, float right, float bottom) :
d_top(top),
d_bottom(bottom),
d_left(left),
d_right(right),
bClean(true)
{
}

hgeRect::hgeRect(Point pos, Size sz) :
d_top(pos.d_y),
d_bottom(pos.d_y + sz.d_y),
d_left(pos.d_x),
d_right(pos.d_x + sz.d_x),
bClean(true)
{
}


/*************************************************************************
Return a hgeRect object that is the intersection of 'this' with 'hgeRect'
*************************************************************************/
hgeRect hgeRect::getIntersection(const hgeRect& rect) const
{
	// check for total exclusion
	if ((d_right > rect.d_left) && (d_left < rect.d_right) &&
			(d_bottom > rect.d_top) && (d_top < rect.d_bottom))
	{
		hgeRect temp;

		// fill in temp with the intersection
		temp.d_left = (d_left > rect.d_left) ? d_left : rect.d_left;
		temp.d_right = (d_right < rect.d_right) ? d_right : rect.d_right;
		temp.d_top = (d_top > rect.d_top) ? d_top : rect.d_top;
		temp.d_bottom = (d_bottom < rect.d_bottom) ? d_bottom : rect.d_bottom;

		return temp;
	}
	else
	{
		return hgeRect(0.0f, 0.0f, 0.0f, 0.0f);
	}

}

/*************************************************************************
Apply an offset the the hgeRect
*************************************************************************/
hgeRect& hgeRect::offset(const Point& pt)
{
	d_left		+= pt.d_x;
	d_right		+= pt.d_x;
	d_top		+= pt.d_y;
	d_bottom	+= pt.d_y;
	return *this;
}


/*************************************************************************
Check if a given point is within the hgeRect
*************************************************************************/
bool hgeRect::isPointInRect(const Point& pt) const
{
	if ((d_left > pt.d_x) ||
		(d_right <= pt.d_x) ||
		(d_top > pt.d_y) ||
		(d_bottom <= pt.d_y))
	{
		return false;
	}

	return true;
}

/*************************************************************************
Set location of hgeRect retaining current size.
*************************************************************************/
void hgeRect::setPosition(const Point& pt)
{
	Size sz(getSize());

	d_left = pt.d_x;
	d_top  = pt.d_y;
	setSize(sz);
}


/*************************************************************************
check the size of the hgeRect object and if it is bigger than 'sz', 
resize it so it isn't.	
*************************************************************************/
hgeRect& hgeRect::constrainSizeMax(const Size& sz)
{
	if (getWidth() > sz.d_x)
	{
		setWidth(sz.d_x);
	}

	if (getHeight() > sz.d_y)
	{
		setHeight(sz.d_y);
	}

	return *this;
}


/*************************************************************************
check the size of the hgeRect object and if it is smaller than 'sz',
resize it so it isn't.
*************************************************************************/
hgeRect& hgeRect::constrainSizeMin(const Size& sz)
{
	if (getWidth() < sz.d_x)
	{
		setWidth(sz.d_x);
	}

	if (getHeight() < sz.d_y)
	{
		setHeight(sz.d_y);
	}

	return *this;
}


/*************************************************************************
check the size of the hgeRect object and if it is bigger than 'max_sz'
or smaller than 'min_sz', resize it so it isn't.
*************************************************************************/
hgeRect& hgeRect::constrainSize(const Size& max_sz, const Size& min_sz)
{
	Size curr_sz(getSize());

	if (curr_sz.d_x > max_sz.d_x)
	{
		setWidth(max_sz.d_x);
	}
	else if (curr_sz.d_x < min_sz.d_x)
	{
		setWidth(min_sz.d_x);
	}

	if (curr_sz.d_y > max_sz.d_y)
	{
		setHeight(max_sz.d_y);
	}
	else if (curr_sz.d_y < min_sz.d_y)
	{
		setHeight(min_sz.d_y);
	}

	return *this;
}

hgeRect& hgeRect::operator=(const hgeRect& rhs)
{
	d_left = rhs.d_left;
	d_top = rhs.d_top;
	d_right = rhs.d_right;
	d_bottom = rhs.d_bottom;

	return *this;
}

void hgeRect::Encapsulate(float x, float y)
{
	if(bClean)
	{
		d_left = d_right = x;
		d_top = d_bottom = y;
		bClean = false;
	}
	else
	{
		if( x < d_left )
			d_left = x;
		if( x > d_right)
			d_right = x;
		if( y < d_top)
			d_top = y;
		if( y > d_bottom)
			d_bottom = y;
	}
}

bool hgeRect::isPointInRect(float x, float y) const
{
	if( x >= d_left && x <= d_right && y >= d_top && y < d_bottom)
		return true;
	return false;
}

bool hgeRect::isIntersect(const hgeRect& rect) const
{
	if(fabs(d_left + d_right - rect.d_left - rect.d_right) < (d_right - d_left + rect.d_right - rect.d_left))
		if(fabs(d_top + d_bottom - rect.d_top - rect.d_bottom) < (d_bottom - d_top + rect.d_bottom - rect.d_top))
			return true;

	return false;
}
